package com.tianji.learning.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CategoryClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CategoryBasicDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.AssertUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.StringUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.entity.InteractionQuestion;
import com.tianji.learning.domain.entity.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.service.IInteractionReplyService;
import com.tianji.learning.service.UserQueryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author author
 */
@Slf4j
@Service
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {
    @Autowired
    private UserClient userClient;

    @Autowired
    private CategoryClient categoryClient;
    @Autowired
    private CourseClient courseClient;
    @Autowired
    private SearchClient searchClient;
    @Autowired
    private CatalogueClient catalogueClient;
    @Autowired
    private IInteractionReplyService replyService;
    @Autowired
    private UserQueryService userQueryService;

    @Override
    public QuestionAdminVO adminQueryQuestionById(Long id) {
        LambdaQueryWrapper<InteractionQuestion> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(InteractionQuestion::getId, id);
        InteractionQuestion one = this.getOne(queryWrapper);
        if (Objects.isNull(one)) {
            throw new BizIllegalException("问题不存在");
        }
        QuestionAdminVO questionAdminVO = BeanUtil.copyProperties(one, QuestionAdminVO.class);
        List<InteractionQuestion> questions = new ArrayList<>();
        questions.add(one);
        //获取章节信息 catalogueMap  章节sectionIds +chapterIds     =catalogueIds
        //获取三级 列表
        List<CategoryBasicDTO> allOfOneLevel = categoryClient.getAllOfOneLevel();
        Map<Long, CategoryBasicDTO> categoryMap = allOfOneLevel.stream().collect(Collectors.toMap(CategoryBasicDTO::getId, Function.identity()));
        //课程信息
        CourseFullInfoDTO courseInfoById = courseClient.getCourseInfoById(one.getCourseId(), true, true);
        //章节信息
        Map<Long, CataSimpleInfoDTO> catalogueMap = getCatalogueMap(questions);
        //获取用户信息
        Map<Long, UserDTO> userMap = userQueryService.getUserMap(questions);
        //填充
        questionAdminVO.setUserIcon(userMap.get(one.getUserId()).getIcon());
        // courseName =》 courseClient
        questionAdminVO.setCourseName(courseInfoById == null ? "" : courseInfoById.getName());
        //设置章节信息
        setCatalogueName(one, questionAdminVO, catalogueMap);
        //获取教师名
        List<Long> teacherIds = courseInfoById.getTeacherIds();
        List<UserDTO> userDTOS = userClient.queryUserByIds(teacherIds);
        UserDTO userDTO = userDTOS.get(0);
        questionAdminVO.setTeacherName(userDTO.getName());
        // categoryName =》 categoryClient
        questionAdminVO.setCategoryName(getCategoryNames(categoryMap, courseInfoById.getFirstCateId(),courseInfoById.getSecondCateId(),courseInfoById.getThirdCateId()));
        //TODO  未完成管理端返回问题评论
        //修改
        InteractionQuestion interactionQuestion = new InteractionQuestion();
        interactionQuestion.setId(id);
        interactionQuestion.setStatus(1);
        interactionQuestion.setUpdateTime(LocalDateTime.now());
        this.updateById(interactionQuestion);
        return questionAdminVO;
    }

    @Override
    public void updateQuestionHidden(Long id, Boolean hidden) {
        LambdaUpdateWrapper<InteractionQuestion> queryWrapper = new LambdaUpdateWrapper<>();
        queryWrapper.eq(InteractionQuestion::getId, id);
        InteractionQuestion interactionQuestion = new InteractionQuestion();
        interactionQuestion.setHidden(hidden);
        interactionQuestion.setUpdateTime(LocalDateTime.now());
        this.update(interactionQuestion, queryWrapper);
    }

    @Override
    public void deleteMyQuestion(Long id) {
        InteractionQuestion questionDB = this.getById(id);
        AssertUtils.isNotNull(questionDB, "问题不存在");
        AssertUtils.isFalse(questionDB.getUserId().equals(UserContext.getUser()), "只能删除自己的提问");
        this.deleteMyQuestion(id);
        LambdaQueryWrapper<InteractionReply> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(InteractionReply::getQuestionId, id);
        replyService.remove(queryWrapper);
    }

    @Override
    public void updateQuestion(Long id, QuestionFormDTO dto) {
        LambdaUpdateWrapper<InteractionQuestion> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(InteractionQuestion::getId, id);
        InteractionQuestion interactionQuestion = BeanUtil.copyProperties(dto, InteractionQuestion.class);
        this.update(interactionQuestion, updateWrapper);
    }

    @Override
    public PageDTO<QuestionAdminVO> queryQuestionPageAdmin(QuestionAdminPageQuery query) {
        Page<InteractionQuestion> page = query.toMpPage("create_time", false);
        LambdaQueryWrapper<InteractionQuestion> queryWrapper = getLambdaQueryWrapper(query);
        if (queryWrapper == null) {
            return PageDTO.empty(page);
        }

        this.page(page, queryWrapper);
        List<InteractionQuestion> questions = page.getRecords();
        if (CollUtils.isEmpty(questions)) {
            return PageDTO.empty(page);
        }
        List<Long> userIds = questions.stream().map(InteractionQuestion::getUserId).collect(Collectors.toList());

        //获取章节信息 catalogueMap  章节sectionIds +chapterIds     =catalogueIds
        Map<Long, CataSimpleInfoDTO> catalogueMap = getCatalogueMap(questions);
        //获取课程信息
        Map<Long, CourseSimpleInfoDTO> courseMap = getCourseMap(questions);
        //获取用户信息
        Map<Long, UserDTO> userMap = userQueryService.getUserMap(questions);
        //获取三级 列表
        List<CategoryBasicDTO> allOfOneLevel = categoryClient.getAllOfOneLevel();
        Map<Long, CategoryBasicDTO> categoryMap = allOfOneLevel.stream().collect(Collectors.toMap(CategoryBasicDTO::getId, Function.identity()));
        List<QuestionAdminVO> questionAdminVOS = new ArrayList<>(questions.size());
        for (InteractionQuestion question : questions) {
            QuestionAdminVO questionAdminVO = BeanUtil.copyProperties(question, QuestionAdminVO.class);
            //chaptername      sectionname
            setCatalogueName(question, questionAdminVO, catalogueMap);
            // courseName =》 courseClient
            CourseSimpleInfoDTO course = courseMap.get(question.getCourseId());
            questionAdminVO.setCourseName(course == null ? "" : course.getName());
            // userName =》 userClient
            UserDTO user = userMap.get(question.getUserId());
            questionAdminVO.setUserName(user == null ? "" : user.getUsername());
            // categoryName =》 categoryClient
            AssertUtils.isNotNull(course, "课程信息不存在");
            questionAdminVO.setCategoryName(getCategoryNames(categoryMap, course));
            questionAdminVOS.add(questionAdminVO);
        }
        return PageDTO.of(page, questionAdminVOS);
    }

    private LambdaQueryWrapper<InteractionQuestion> getLambdaQueryWrapper(QuestionAdminPageQuery query) {
        LambdaQueryWrapper<InteractionQuestion> queryWrapper = new LambdaQueryWrapper<>();
        // courseName->courseIds
        if (StringUtils.isNotBlank(query.getCourseName())) {
            List<Long> courseIds = searchClient.queryCoursesIdByName(query.getCourseName());
            if (CollUtils.isEmpty(courseIds)) {
                return null;
            }
            queryWrapper.in(InteractionQuestion::getCourseId, courseIds);
        }
        queryWrapper.eq(query.getStatus() != null, InteractionQuestion::getStatus, query.getStatus());
        queryWrapper.ge(query.getBeginTime() != null, InteractionQuestion::getCreateTime, query.getBeginTime());
        queryWrapper.le(query.getEndTime() != null, InteractionQuestion::getCreateTime, query.getEndTime());
        return queryWrapper;
    }

    private void setCatalogueName(InteractionQuestion question, QuestionAdminVO questionAdminVO, Map<Long, CataSimpleInfoDTO> catalogueMap) {
        CataSimpleInfoDTO chapter = catalogueMap.get(question.getChapterId());
        CataSimpleInfoDTO section = catalogueMap.get(question.getSectionId());
        questionAdminVO.setChapterName(chapter == null ? "" : chapter.getName());
        questionAdminVO.setSectionName(section == null ? "" : section.getName());
    }

    private String getCategoryNames(Map<Long, CategoryBasicDTO> categoryMap, CourseSimpleInfoDTO course) {
        CategoryBasicDTO category1 = categoryMap.get(course.getFirstCateId());
        CategoryBasicDTO category2 = categoryMap.get(course.getSecondCateId());
        CategoryBasicDTO category3 = categoryMap.get(course.getThirdCateId());
        return (category1 == null ? "" : category1.getName()) + "/" + (category2 == null ? "" : category2.getName()) + "/" + (category3 == null ? "" : category3.getName());
    }
    private String getCategoryNames(Map<Long, CategoryBasicDTO> categoryMap, Long firstCateId,Long secondCateId,Long thirdCateId) {
        CategoryBasicDTO category1 = categoryMap.get(firstCateId);
        CategoryBasicDTO category2 = categoryMap.get(secondCateId);
        CategoryBasicDTO category3 = categoryMap.get(thirdCateId);
        return (category1 == null ? "" : category1.getName()) + "/" + (category2 == null ? "" : category2.getName()) + "/" + (category3 == null ? "" : category3.getName());
    }

    /*private Map<Long, UserDTO> getUserMap(List<InteractionQuestion> questions) {
        Map<Long, UserDTO> userMap = new HashMap<>();
        List<Long> userIds = questions.stream().map(InteractionQuestion::getUserId).collect(Collectors.toList());
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        if (!CollUtils.isEmpty(userDTOS)) {
            userMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
        }
        return userMap;
    }*/

    private Map<Long, CourseSimpleInfoDTO> getCourseMap(List<InteractionQuestion> questions) {
        Map<Long, CourseSimpleInfoDTO> courseMap = new HashMap<>();
        List<Long> courseIds = questions.stream().map(InteractionQuestion::getCourseId).collect(Collectors.toList());
        List<CourseSimpleInfoDTO> courseSimpleInfoDTOS = courseClient.getSimpleInfoList(courseIds);
        if (!CollUtils.isEmpty(courseSimpleInfoDTOS)) {
            courseMap = courseSimpleInfoDTOS.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, Function.identity()));
        }
        return courseMap;
    }

    private Map<Long, CataSimpleInfoDTO> getCatalogueMap(List<InteractionQuestion> questions) {
        Map<Long, CataSimpleInfoDTO> catalogueMap = new HashMap<>();
        HashSet<Long> catalogueIds = new HashSet<>();
        questions.stream().forEach(question -> {
            if (question.getSectionId() != null) {
                catalogueIds.add(question.getSectionId());
            }
            if (question.getChapterId() != null) {
                catalogueIds.add(question.getChapterId());
            }
        });
        if (CollUtils.isNotEmpty(catalogueIds)) {
            List<CataSimpleInfoDTO> cataSimpleInfoDTOS = catalogueClient.batchQueryCatalogue(catalogueIds);
            if (CollUtils.isNotEmpty(cataSimpleInfoDTOS)) {
                catalogueMap = cataSimpleInfoDTOS.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, cataSimpleInfoDTO -> cataSimpleInfoDTO));
            }
        }
        return catalogueMap;
    }

    @Override
    public QuestionVO queryQuestionById(Long id) {
        LambdaQueryWrapper<InteractionQuestion> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(InteractionQuestion::getId, id);
//        queryWrapper.eq(InteractionQuestion::getUserId, UserContext.getUser());
        queryWrapper.eq(InteractionQuestion::getHidden, false);
        InteractionQuestion one = this.getOne(queryWrapper);
        if (Objects.isNull(one)) {
            new QuestionVO();
        }
        QuestionVO questionVO = BeanUtil.copyProperties(one, QuestionVO.class);
        //用户名头像
        UserDTO user = userClient.queryUserById(one.getUserId());
        if (!one.getAnonymity()) {
            questionVO.setUserName(user == null ? "" : user.getName());
            questionVO.setUserIcon(user == null ? "" : user.getIcon());
        } else {
            questionVO.setUserName("匿名用户");
        }
        return questionVO;
    }

    @Override
    public void saveInteractionQuestion(QuestionFormDTO dto) {
        InteractionQuestion interactionQuestion = BeanUtil.copyProperties(dto, InteractionQuestion.class);
        interactionQuestion.setUserId(UserContext.getUser());
        interactionQuestion.setHidden(false);
        interactionQuestion.setStatus(QuestionStatus.UN_CHECK.getValue());
        interactionQuestion.setAnswerTimes(0);
        LocalDateTime now = LocalDateTime.now();
        interactionQuestion.setCreateTime(now);
        interactionQuestion.setUpdateTime(now);
        this.save(interactionQuestion);
    }

    @Override
    public PageDTO<QuestionVO> queryQuestionPage(QuestionPageQuery dto) {
        Page<InteractionQuestion> page = dto.toMpPage("create_time", false);
        LambdaQueryWrapper<InteractionQuestion> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(dto.getCourseId() != null, InteractionQuestion::getCourseId, dto.getCourseId());
        queryWrapper.eq(dto.getSectionId() != null, InteractionQuestion::getSectionId, dto.getSectionId());
        queryWrapper.eq(dto.getOnlyMine() != null&&dto.getOnlyMine(), InteractionQuestion::getUserId, UserContext.getUser());
        queryWrapper.eq(InteractionQuestion::getHidden, false);
        this.page(page, queryWrapper);
        List<InteractionQuestion> records = page.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }
        //查询latest_reply_content latest_reply_user    latestAnswerId
        List<InteractionReply> interactionReplies = null;
        Map<Long, InteractionReply> replyMap = null;
        List<Long> replieUserIds = null;
        List<Long> replyIds = records.stream().filter(q -> q.getLatestAnswerId() != null).map(InteractionQuestion::getLatestAnswerId).collect(Collectors.toList());
        if (CollUtils.isNotEmpty(replyIds)) {
            interactionReplies = replyService.listByIds(replyIds);
            replieUserIds = interactionReplies.stream().map(InteractionReply::getUserId).collect(Collectors.toList());
            if (CollUtils.isEmpty(interactionReplies)) {
                log.info("查询不到reply信息：{}", interactionReplies);
                throw new BizIllegalException("网络异常");
            }
            replyMap = interactionReplies.stream().collect(Collectors.toMap(c -> c.getId(), c -> c));
        }
        //查询user表信息
        List<Long> userIds = records.stream().filter(q -> q.getAnonymity() == null || !q.getAnonymity()).map(InteractionQuestion::getUserId).collect(Collectors.toList());
        //合并需要查询的userIds
        HashSet<Long> unionUserIds = new HashSet<>();
        if (CollUtils.isNotEmpty(userIds)) {
            unionUserIds.addAll(userIds);
        }
        if (CollUtils.isNotEmpty(replieUserIds)) {
            unionUserIds.addAll(replieUserIds);
        }
        Map<Long, UserDTO> userDTOMap = new HashMap<>();
        if (!CollUtils.isEmpty(unionUserIds)) {
            List<UserDTO> userDTOS = userClient.queryUserByIds(unionUserIds);
            userDTOMap = userDTOS.stream().collect(Collectors.toMap(c -> c.getId(), c -> c));
        }
        //导入数据
        List<QuestionVO> voList = new ArrayList<>();
        for (InteractionQuestion question : records) {
            QuestionVO vo = BeanUtil.copyProperties(question, QuestionVO.class);
            // username usericon
            UserDTO user = userDTOMap.get(vo.getUserId());
            if (!Objects.isNull(user) && !question.getAnonymity()) {
                vo.setUserName(user == null ? "" : user.getName());
                vo.setUserIcon(user == null ? "" : user.getIcon());
            } else {
                vo.setUserName("匿名用户");
            }
            // latest_reply_content latest_reply_user
            if (CollUtils.isNotEmpty(replyMap) && question.getLatestAnswerId() != null) {
                InteractionReply reply = replyMap.get(question.getLatestAnswerId());
                vo.setLatestReplyContent(reply == null ? "" : reply.getContent());
                if (reply != null && reply.getAnonymity() != null && !reply.getAnonymity()) {
                    Long replyUserId = reply.getUserId();
                    UserDTO replyUser = userDTOMap.get(replyUserId);
                    vo.setLatestReplyUser(replyUser == null ? "" : replyUser.getName());
                } else {
                    vo.setLatestReplyUser("匿名用户");
                }
            }
            voList.add(vo);
        }
        return PageDTO.of(page, voList);
    }
}
